/* Emergent Zebra Stripes */

float threshold = .56; // Threshold for "diversity" between 0 and 1
int hoodRadius = 3;    // How large is a cell's neighborhood
float neighbors = (4*hoodRadius*hoodRadius) + (4*hoodRadius);

/* Display variables */
int cellSize = 1;
int cellsX = 400;
int cellsY = 400;

/* The world */
boolean[][] grid = new boolean[cellsX][cellsY];

/* Our colors */
color black  = #FFFFFF;
color white  = #000000;

/* Click to start */
void setup() {
  background(#FFFFFF);
  noStroke();
  size(cellsX*cellSize, cellsY*cellSize, P2D);
  seedGrid();
  colorGrid();
}

void draw() {
  shuffle();
  colorGrid();
}

void seedGrid() {
  for(int x = 0; x < cellsX; x++) {
    for(int y = 0; y < cellsY; y++) {
      float densityChance = random(1.0);
      if (densityChance < .5) {
        grid[x][y] = true;
      } else {
        grid[x][y] = false;
      }
    }
  }
}

void colorGrid() {
  for(int x = 0; x < cellsX; x++) {
    for(int y = 0; y < cellsY; y++) {
      if(grid[x][y] == false) {
        fill(black);
      } else {
        fill(white);
      }
      rect(x*cellSize,y*cellSize,cellSize,cellSize);  
    }
  }
}

void shuffle() {
  for(int x = 0; x < cellsX; x++) {
    for(int y = 0; y < cellsY; y++) {
      if(numDifferent(x,y)/neighbors >= threshold) {
        move(x,y);
      }
    }
  }
}

int numDifferent(int x, int y) {
  int different = 0;
  for(int i = x-hoodRadius; i <= x+hoodRadius; i++) {
    for(int j = y-hoodRadius; j <= y+hoodRadius; j++) {
      if(grid[x][y] != grid[(i+cellsX)%cellsX][(j+cellsY)%cellsY]) {
        different++;
      }
    }
  }
  return different;
}

void move(int x, int y) {
  boolean tmp = grid[x][y];
  grid[x][y] = grid[(x+1)%cellsX][y];
  grid[(x+1)%cellsX][y] = tmp;
}
